package cn.miju.admin.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.miju.admin.framework.model.BasePage;
import cn.miju.admin.system.service.DictService;
import cn.miju.admin.system.vo.*;
import cn.miju.database.entity.SysDict;
import cn.miju.database.entity.SysDictDetail;
import cn.miju.database.mapper.SysDictDetailMapper;
import cn.miju.database.mapper.SysDictMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <pre>
 * 字典管理
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-04-06 16:26
 */
@Service
@RequiredArgsConstructor
public class DictServiceImpl implements DictService {
    private final SysDictMapper sysDictMapper;
    private final SysDictDetailMapper sysDictDetailMapper;

    /**
     * 获取字典树
     * @return {@link List<DictTreeOutVO>}
     */
    @Override
    public List<DictTreeOutVO> getTree() {
        List<SysDict> sysDictList = sysDictMapper.selectList(Wrappers.<SysDict>lambdaQuery().isNull(SysDict::getParentId));
        List<DictTreeOutVO> outVOList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(sysDictList)) {
            List<SysDict> secondSysDictList = sysDictMapper.selectList(Wrappers.<SysDict>lambdaQuery().in(SysDict::getParentId, sysDictList.stream().map(SysDict::getId).collect(Collectors.toList())));
            Map<Long, List<SysDict>> secondSysDictMap = Maps.newHashMap();
            if (CollUtil.isNotEmpty(secondSysDictList)) {
                secondSysDictMap.putAll(secondSysDictList.stream().collect(Collectors.groupingBy(SysDict::getParentId, Collectors.mapping(sysDict -> sysDict, Collectors.toList()))));
            }
            outVOList.addAll(sysDictList.stream().map(sysDict -> {
                DictTreeOutVO outVO = new DictTreeOutVO();
                outVO.setId(sysDict.getId());
                outVO.setCode(sysDict.getDictCode());
                outVO.setName(sysDict.getDictName());
                List<SysDict> secondSysDictLists = secondSysDictMap.getOrDefault(sysDict.getId(), null);
                if (CollUtil.isNotEmpty(secondSysDictLists)) {
                    outVO.setChildren(secondSysDictLists.stream().map(secondSysDict -> {
                        DictTreeOutVO secondOutVO = new DictTreeOutVO();
                        secondOutVO.setId(secondSysDict.getId());
                        secondOutVO.setParentId(secondSysDict.getParentId());
                        secondOutVO.setCode(secondSysDict.getDictCode());
                        secondOutVO.setName(secondSysDict.getDictName());
                        return secondOutVO;
                    }).collect(Collectors.toList()));
                }
                return outVO;
            }).collect(Collectors.toList()));
        }
        return outVOList;
    }

    /**
     * 保存字典
     * @param inVO {@link DictSaveInVO}
     */
    @Override
    public void save(DictSaveInVO inVO) {
        if (null == inVO.getId()) {
            sysDictMapper.insert(SysDict.builder().dictCode(inVO.getCode()).dictName(inVO.getName()).parentId(inVO.getParentId()).build());
        } else {
            sysDictMapper.update(null, Wrappers.<SysDict>lambdaUpdate().
                    set(SysDict::getDictCode, inVO.getCode()).
                    set(SysDict::getDictName, inVO.getName()).
                    set(SysDict::getUpdatedTime, LocalDateTime.now()).
                    eq(SysDict::getId, inVO.getId()));
        }
    }

    /**
     * 批量删除字典
     * @param inVO {@link DictDeleteInVO}
     */
    @Override
    public void deletes(DictDeleteInVO inVO) {
        sysDictMapper.deleteBatchIds(inVO.getIds());
        sysDictDetailMapper.delete(Wrappers.<SysDictDetail>lambdaQuery().in(SysDictDetail::getDictId, inVO.getIds()));
    }

    /**
     * 保存字典明细
     * @param inVO {@link DictSaveDetailInVO}
     */
    @Override
    public void saveDetail(DictSaveDetailInVO inVO) {
        if (null == inVO.getId()) {
            sysDictDetailMapper.insert(SysDictDetail.builder().
                    dictId(inVO.getDictId()).
                    subName(inVO.getName()).
                    subValue(inVO.getValue()).
                    build());
        } else {
            sysDictDetailMapper.update(null, Wrappers.<SysDictDetail>lambdaUpdate().
                    set(SysDictDetail::getDictId, inVO.getDictId()).
                    set(SysDictDetail::getSubName, inVO.getName()).
                    set(SysDictDetail::getSubValue, inVO.getValue()).
                    set(SysDictDetail::getDictId, inVO.getDictId()).
                    eq(SysDictDetail::getId, inVO.getId()));
        }
    }

    /**
     * 字典明细分页查询
     * @param inVO {@link DictDetailPageInVO}
     * @return {@link Page<DictDetailPageOutVO>}
     */
    @Override
    public Page<DictDetailPageOutVO> getDetailPage(DictDetailPageInVO inVO) {
        Page<SysDictDetail> sysDictDetailPage = sysDictDetailMapper.selectPage(new Page<>(inVO.getPage(), inVO.getPageSize()),
                Wrappers.<SysDictDetail>lambdaQuery().eq(SysDictDetail::getDictId, inVO.getDictId()));
        Page<DictDetailPageOutVO> page = new Page<>();
        BeanUtil.copyProperties(sysDictDetailPage, page);
        if (CollUtil.isNotEmpty(sysDictDetailPage.getRecords())) {
            page.setRecords(sysDictDetailPage.getRecords().stream().map(sysDictDetail -> {
                DictDetailPageOutVO outVO = new DictDetailPageOutVO();
                outVO.setId(sysDictDetail.getId());
                outVO.setDictId(sysDictDetail.getDictId());
                outVO.setName(sysDictDetail.getSubName());
                outVO.setValue(sysDictDetail.getSubValue());
                return outVO;
            }).collect(Collectors.toList()));
        }
        return page;
    }

    /**
     * 批量删除字典明细
     * @param inVO {@link DictDeleteInVO}
     */
    @Override
    public void detailDeletes(DictDeleteInVO inVO) {
        sysDictDetailMapper.deleteBatchIds(inVO.getIds());
    }
}
